package com.horoscope.astrology.zodiac.signs.free.utils.ad.ad_implement

import android.app.Activity
import android.util.Log
import com.google.android.gms.ads.*
import com.google.android.gms.ads.formats.NativeAdOptions
import com.google.android.gms.ads.formats.UnifiedNativeAd
import com.google.android.gms.ads.rewarded.RewardedAd
import com.google.android.gms.ads.rewarded.RewardedAdCallback
import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback
import com.horoscope.astrology.zodiac.signs.free.AppSettingManager
import com.horoscope.astrology.zodiac.signs.free.BuildConfig
import com.horoscope.astrology.zodiac.signs.free.MmoApplication
import com.horoscope.astrology.zodiac.signs.free.R
import com.horoscope.astrology.zodiac.signs.free.bean.ConfigResultBean
import com.horoscope.astrology.zodiac.signs.free.utils.EventType
import com.horoscope.astrology.zodiac.signs.free.utils.FlurryEventUtil
import com.horoscope.astrology.zodiac.signs.free.utils.interfaceUtils.GoogleInterstitialListener
import com.horoscope.astrology.zodiac.signs.free.utils.interfaceUtils.GoogleNativeListener
import com.horoscope.astrology.zodiac.signs.free.utils.interfaceUtils.GoogleRewardListener
import com.jeremyliao.liveeventbus.LiveEventBus
import java.util.*
import kotlin.collections.ArrayList


/**
 * 务必在展示插页式广告时暂停操作。
 * 插页式广告类型多样，包括文字广告、图片广告和视频广告等。确保应用在展示插页式广告时，也会暂停使用某些资源，
 * 以便供广告使用，这一点十分重要。例如，当您发出展示插页式广告的调用后，请务必暂停应用产生的所有音频输出。
 * 您可以在 onAdClosed() 事件处理脚本中恢复声音播放，该处理脚本会在用户结束与广告的互动之后被调用。此外，
 * 请考虑在广告展示时暂停所有密集计算任务（例如游戏循环）。这将确保用户不会遇到图像无响应/响应慢或者视频卡顿的现象。
 *
 * 留出充足的加载时间。
 * 确保在恰当的时间展示插页式广告十分重要，同样，确保用户无需等待广告加载也十分重要。在您打算调用 show() 前，
 * 请事先通过调用 loadAd() 加载广告，这可确保应用在广告展示时间来临前，准备好已完全加载的插页式广告。
 * */
class LoadGoogleAd private constructor() {

    private val mContext = MmoApplication.getInstance()

    private var mInterstitialAd: InterstitialAd? = null
    private var mUnifiedNativeAd: UnifiedNativeAd? = null
    private var mRewardedVideoAd: RewardedAd? = null

    private var adList = Collections.synchronizedList(ArrayList<UnifiedNativeAd>())
    private var iList = Collections.synchronizedList(ArrayList<InterstitialAd>())
    private var rList = Collections.synchronizedList(ArrayList<RewardedAd>())

    private var adLoader: AdLoader? = null

    // 用于打点
    private var iPlacement = ""
    private var nPlacement = ""
    private var rPlacement = ""

    private var mGoogleInterstitialListener: GoogleInterstitialListener? = null
    private var mGoogleNativeListener: GoogleNativeListener? = null
    private var mGoogleRewardListener: GoogleRewardListener? = null

    fun setGoogleInterstitialListener(listener: GoogleInterstitialListener) {
        mGoogleInterstitialListener = listener
    }

    fun setGoogleNativeListener(listener: GoogleNativeListener) {
        mGoogleNativeListener = listener
    }

    fun setGoogleRewardListener(listener: GoogleRewardListener) {
        mGoogleRewardListener = listener
    }


    companion object {
        const val BANNER_CACHE_NUM = 2
        const val INSERT_CACHE_NUM = 1
        val mInstance by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
            LoadGoogleAd()
        }
    }


    /**interstitial广告数据准备，初始化对象，加载对象，显示广告**/

    // 数据已加载 初始化实例 添加监听 加载广告
    @Synchronized
    fun initInsertAD(bean: ConfigResultBean.AdInfo) {
        if (mInterstitialAd != null) mInterstitialAd = null
        mInterstitialAd = InterstitialAd(mContext).apply {
            adUnitId = getAdId(1, bean.id)
            adListener = initInterstitialAdListener(bean)
            loadAd(getRequest())
        }
    }

    private var errorNum = 0

    // 插屏广告的监听回调
    private fun initInterstitialAdListener(bean: ConfigResultBean.AdInfo): AdListener =
        object : AdListener() {

            //广告加载完
            override fun onAdLoaded() {
                mInterstitialAd?.let {
                    if (mInterstitialAd!!.isLoaded) {
                        iList.add(mInterstitialAd)  // 放到缓存备用
                        mGoogleInterstitialListener?.onGoogleADLoad(bean) // 将广告位ID放入队列以对应缓存
                        mInterstitialAd = null
                        Log.e("wsTest", "GoogleInterstitial成功")
                    }
                }
            }

            //广告请求失败
            override fun onAdFailedToLoad(errorCode: Int) {
                mGoogleInterstitialListener?.onGoogleFailed(errorCode.toString())
                errorNum++
                if (errorNum % 5 == 0)
                    FlurryEventUtil.putDataToEvent(
                        "AdMob_InterstitialAd_Error",
                        "type",
                        errorCode.toString()
                    )
                Log.e("wsTest", "InterErrorCode:$errorCode")
            }

            //显示广告时要执行的代码 在广告开始展示并铺满设备屏幕时，系统会调用此方法。
            override fun onAdOpened() {
                if (iPlacement != "Supplement") {
                    FlurryEventUtil.putDataToEvent(
                        EventType.TYPE_AD_DISPLAY, "type", iPlacement
                    )
                }
                mListener?.onOpen()
            }

            override fun onAdClicked() {
                FlurryEventUtil.putDataToEvent(EventType.TYPE_AD_CLICK, "type", iPlacement)
            }

            override fun onAdClosed() {
                mListener?.onClose()
            }
        }

    // Show 插页广告
    fun showInterstitialAd(placement: String, time: Int): Boolean {
        iPlacement = placement
        var isShow = false
        if (iList.isNotEmpty()) {
            iList.firstOrNull()?.let {
                if (it.isLoaded) {
                    it.show()
                    iList.remove(it)
//                    GlobalScope.launch(Dispatchers.Main) {
//                        delay(2500L)
//                        ADInterstitialManager.mInstance.getInterstitialFirst()
//                    }
                    supplement()
                    FlurryEventUtil.putDataToEvent(
                        EventType.TYPE_IS_READY,
                        "Interstitial",
                        "True_$time"
                    )
                    isShow = true
                } else {
                    FlurryEventUtil.putDataToEvent(
                        EventType.TYPE_IS_READY,
                        "Interstitial",
                        "False_$time"
                    )
                }
            }
        } else {
            AppSettingManager.saveInt(1, "supplement")//没有加载，需要补充一次 num = 1
        }
        return isShow
    }

    /**interstitial广告数据准备，初始化对象，加载对象，显示广告**/


    /**rewardl广告数据准备，初始化对象，加载对象，显示广告**/

    // 奖励广告
    @Synchronized
    fun initRewardAD(bean: ConfigResultBean.AdInfo) {
        if (mRewardedVideoAd != null) mRewardedVideoAd = null
        mRewardedVideoAd = RewardedAd(mContext, getAdId(3, bean.id))
        mRewardedVideoAd!!.loadAd(getRequest(), initRewardAdLoadCallback(bean))
    }

    // 视频广告（奖励）的监听回调AdRewardManager中的方法
    private fun initRewardAdLoadCallback(bean: ConfigResultBean.AdInfo): RewardedAdLoadCallback {
        return object : RewardedAdLoadCallback() {
            override fun onRewardedAdLoaded() {
                if (mRewardedVideoAd!!.isLoaded) {
                    rList.add(mRewardedVideoAd)
                    mGoogleRewardListener?.onGoogleRewardLoad(bean)
                    Log.e("wsTest", "Reward成功")
                }
            }

            override fun onRewardedAdFailedToLoad(errorCode: Int) {
                // 广告加载失败时，将调用此方法
                mGoogleRewardListener?.onGoogleRewardFailed()
                Log.e("wsTest", "Reward失败:$errorCode")
            }
        }
    }

    // show激励广告（新版本api现在需要传callback）
    fun showRewardedVideoAd(
        bean: ConfigResultBean.AdInfo,
        placement: String,
        activity: Activity,
        position: Int,
        time: Int
    ): Boolean {
        rPlacement = placement
        var isShow = false
        val adCallback = object : RewardedAdCallback() {
            override fun onUserEarnedReward(p0: com.google.android.gms.ads.rewarded.RewardItem) {
                /**
                 * 当用户因与广告互动而获得奖励时，将调用该方法。
                 * 可以通过参数的getType()和getAmount()方法
                 * 访问为广告单元配置的奖励详细信息RewardItem
                 */
                LiveEventBus.get(placement).post(position)
            }

            override fun onRewardedAdOpened() {
                FlurryEventUtil.putDataToEvent(EventType.TYPE_AD_DISPLAY, "type", rPlacement)
            }

            override fun onRewardedAdClosed() {}
        }

        if (rList.isNotEmpty()) {
            rList.firstOrNull()?.let {
                if (it.isLoaded) {
                    it.show(activity, adCallback)
                    rList.remove(it)
//                    GlobalScope.launch(Dispatchers.Main) {
//                        delay(2500L)
//                        ADRewardManager.mInstance.getRewardFirst()
//                    }
                    FlurryEventUtil.putDataToEvent(EventType.TYPE_IS_READY, "Reward", "True_$time")
                    isShow = true
                } else {
                    FlurryEventUtil.putDataToEvent(EventType.TYPE_IS_READY, "Reward", "False_$time")
                }
            }
        }
        return isShow
    }

    /**rewardl广告数据准备，初始化对象，加载对象，显示广告**/


    /**native广告数据准备，初始化对象，加载对象，显示广告**/

    // 当原生广告数据加载完毕后 构建原生广告AdLoader 本机模板即项目里的Native项目暂不支持AndroidX
    fun initNativeAd(bean: ConfigResultBean.AdInfo) {
        // 每次调用新广告，要处理旧广告资源
        // 否则会发生内存泄漏。
        mUnifiedNativeAd?.destroy()
        adLoader = AdLoader.Builder(mContext, getAdId(2, bean.id))
            .forUnifiedNativeAd { unifiedNativeAd ->
                if (adLoader!!.isLoading) {
                    mGoogleNativeListener?.onGoogleNativeLoad(bean)
                    adList.add(unifiedNativeAd)
                    Log.e("wsTest", "Native成功")
                }
            }
            .withAdListener(object : AdListener() { //可选方法（广告生命周期事件）
                override fun onAdFailedToLoad(p0: Int) {
                    Log.e("wsTest", "Native失败：$p0")
                    mGoogleNativeListener?.onGoogleNativeFailed("$p0")
                }

                override fun onAdClicked() {
                    FlurryEventUtil.putDataToEvent(EventType.TYPE_AD_CLICK, "type", nPlacement)
                }

                override fun onAdImpression() {
                    if (nPlacement != "Supplement")
                        FlurryEventUtil.putDataToEvent(
                            EventType.TYPE_AD_DISPLAY, "type", nPlacement
                        )
                }
            })
            .withNativeAdOptions(
                // 将广告选择叠加层设置为左上角
                NativeAdOptions.Builder()
                    .setAdChoicesPlacement(NativeAdOptions.ADCHOICES_TOP_LEFT)
                    .setVideoOptions(VideoOptions.Builder().setStartMuted(true).build())
                    .build()
            )
            .build()
        adLoader?.loadAds(getRequest(), 2) // loadAds()方法目前仅适用于AdMob广告 最多五条
    }

    fun getNativeAd(placement: String, time: Int): UnifiedNativeAd? {
        nPlacement = placement
        var temp: UnifiedNativeAd? = null
        if (adList.isNotEmpty()) {
            temp = adList.firstOrNull()
            adList.remove(temp)
            FlurryEventUtil.putDataToEvent(EventType.TYPE_IS_READY, "Native", "True_$time")
        } else {
            FlurryEventUtil.putDataToEvent(EventType.TYPE_IS_READY, "Native", "False_$time")
        }
        return temp
    }

    /**native广告数据准备，初始化对象，加载对象，显示广告**/

// type : 1插页 2原生 3激励
    private fun getAdId(type: Int, id: String): String {
        return if (BuildConfig.DEBUG) {
            when (type) {
                1 -> mContext.getString(R.string.interstitial_test_id)
                2 -> mContext.resources.getString(R.string.native_ad_id_text)
                3 -> mContext.resources.getString(R.string.reward_test_id)
                else -> id
            }
        } else {
            id
        }
    }

    // 载入广告单个参数(测试设备(模拟器不用管)-> logcat中查找 I/Ads: Use AdRequest.Builder.addTestDevice)
// 横幅 插页 原生 公用
    fun getRequest(): AdRequest {
        return if (BuildConfig.DEBUG) {
            val testDeviceIds =
                listOf("C73A0B4E892B6BA757D97D70B24A8960", "5945462D47088AD2A3C33548599312EB")
            val configuration =
                RequestConfiguration.Builder().setTestDeviceIds(testDeviceIds).build()
            MobileAds.setRequestConfiguration(configuration)
            AdRequest.Builder().build()
        } else {
            AdRequest.Builder()
                .build()
        }
    }

    // 是否正常显示了广告，在本地sp做记录
    private fun supplement() {
        if (AppSettingManager.readInt("supplement", 0) == 1) {//补充展示AD，标志位置0
            AppSettingManager.saveInt(0, "supplement")
            FlurryEventUtil.putDataToEvent(
                EventType.TYPE_AD_INTERSTITIAL_DISPLAY, "type", "Supplement"
            )
        } else {//正常展示广告
            FlurryEventUtil.putDataToEvent(
                EventType.TYPE_AD_INTERSTITIAL_DISPLAY, "type", "Correct"
            )
        }
    }

    private var mListener: AdClose? = null

    fun setOnAdCloseListener(listener: AdClose) {
        mListener = listener
    }

    // 用户对广告打开 or 关闭的回调
    interface AdClose {
        fun onClose()
        fun onOpen()
    }

}